#ifndef _FILE_H
#define	_FILE_H

#include <vector>
#include "FreeList.h"
#include "FSBlock.h"
#include "Directory.h"
#include <string>


using namespace std;

class File {
private:
  static Directory *m_dir_static;
  Directory *m_dir;
  FreeList *freelist;
  static FreeList *m_mother_static;
  Disk *m_disk;
  string m_filename;

  /**
   * File Control Block
   */
  FSBlock*    fcb;

  /**
   * Block Group for the File.
   */
  BlockGroup* file_block_group;

  /**
   * Index of data member for use with BlockLinkedList::SetInt()
   */
  static const int START_BLOCK_PTR_INDEX = 0;
  static const int END_BLOCK_PTR_INDEX   = 1;
  static const int NUM_BLOCKS_PTR_INDEX  = 2;
  static const int NUM_BYTES_PTR_INDEX   = 3;
  
  static const bool OPEN_READ_MODE  = true;
  static const bool OPEN_WRITE_MODE = false;

  /**
   * File is open in read mode.
   */
  bool open_read;

  /**
   * File is open in write mode.
   */
  bool open_write;

  /**
   * Points to the current byte in the file
   */
  unsigned int file_pointer;

  /**
   * Points to the FSBlock which we're looking at.
   * @seealso file_pointer
   */
  FSBlock* file_block_pointer;

  unsigned int file_size;
  


public:
  /**
   * Open a damn file.
   * @param filename Name of the file that was to be opened. There might be
   *        more than one possible filename that could refer to the file.
   * @param create Create the file if true.
   * @param read_mode Open file in read-mode if true.
   *                  If false, open in write mode.
   * @param disk pointer to the Disk.
   * @param directory The Directory as a pointer.
   */
  File(string filename, bool create, bool read_mode, Disk *disk,
    Directory *directory);

  /**
   * Destructor
   */
  ~File();

  /**
   * Access filename.
   * @return string Name of file.
   */
  int get_name();

  /**
   * Open file file up.
   * @param mode one of OPEN_WRITE_MODE or OPEN_READ_MODE.
   * @return true iff open() worked.
   */
  bool open(bool mode);

  /**
   * Close file.
   * @return true iff close() worked.
   */
  bool close();

  /**
   * Writes an arbitrary length sequence of bytes to an open file.
   * The write method should append to the file-- i.e., when you open a file to
   * write, it should always start writing at the current end of the file.
   * @return -1 if failure, otherwise the number of bytes that were written.
   */
  int write(unsigned char *data, int data_length);

  /**
   * Reads an arbitrary length sequence of bytes from an open file. Reads from beginning of file until End of File or we've read data_length bytes.
   * @return -1 if failure, otherwise the number of bytes that were read.
   * @param data Buffer to put data into once we've read it.
   * @param data_length How many bytes to read.
   */
  int read(unsigned char *data, int data_length);


  /**
   * Used by testing somehow.
   */
  static void InitClass(Directory *dir, FreeList *mother);

    /** Carry out menu-based testing.
     */
    static void Test();
};



#endif	/* _FILE_H */

